Expand description
This crate provides an ergonomic, type-safe, and aesthetically-pleasing Size type that can
be used to express, format, or operate on sizes. While it was initially created to make it
painless to “pretty print” file sizes (by automatically determining which unit and with what
precision a file size should be textually “written out” or formatted), it has expanded in scope
to make it easier and safer to perform the different types of operations that would arise when
dealing with sizes.
For almost all users, the only surface of interaction with this crate will take place via the
Size type, which can be used to create a strongly-typed representation of a file size (or any
other “size” you need to deal with in the abstract). This crate’s API is intended to be as
natural and intuitive as possible, providing sensible defaults with zero boilerplate but also
allowing the developer to manually control aspects how sizes are expressed as text if needed.
The core Size type is a simple wrapper around a signed numeric value - it can be initialized
using whatever primitive numeric type you wish, e.g. constructing a Size from an i64 or from
a foo: f64 number of kilobytes.
§Using this crate and creating a Size object
To use this crate, you only need to place use size::Size at the top of your rust code, then
create a Size from a constructor/initializer that matches the size you have on hand. Both
base-2 (KiB, MiB, etc) and base-10 (KB, MB, etc) units are supported and are exposed via the
same API. You can either use the abbreviated form of the unit to instantiate your type, or use
the full unit name to be more expressive. Here’s an example:
use size::Size;
// Create a strongly-typed size object. We don't even need to specify a numeric type!
let file1_size = Size::from_bytes(200);
// Create another Size instance, this time from a floating-point literal:
let file2_size = Size::from_kb(20.1);You can obtain a scalar i64 value equal to the total number of bytes described by a
Size instance by calling Size::bytes() (see link for more info):
use size::Size;
let file_size = Size::from_gibibytes(4);
assert_eq!(file_size.bytes(), 4_294_967_296);All Size types can be directly compared (both for order and equality) to one another (or to
references of one another), regardless of their original type:
use size::Size;
let size1 = Size::from_kib(4 as u8);
let size2 = Size::from_bytes(4096 as i64);
assert_eq!(size1, size2);
let size1 = Size::from_kib(7);
let size2 = Size::from_kb(7);
assert!(&size2 < &size1);§Textual representation
The majority of users will be interested in this crate for its ability to “pretty print” sizes
with little ceremony and great results. All Size instances implement both
std::fmt::Display and std::fmt::Debug, so you can just directly format!(...) or
println!(...) with whatever Size you have on hand:
use size::Size;
let file_size = Size::from_bytes(1_340_249);
let textual = format!("{}", file_size); // "1.28 MiB"
assert_eq!(textual.as_str(), "1.28 MiB");Size::to_string() can be used to directly return a String containing the formatted,
human-readable size, instead of needing to use the format!() macro or similar:
use size::Size;
let file_size = Size::from_bytes(1_340_249);
assert_eq!(file_size.to_string(), "1.28 MiB".to_string());For fine-grained control over how a size is formatted and displayed, you can manually use the
Size::format() function, which returns a FormattableSize
implementing the builder model to allow you to change one or more properties of how a Size
is formatted:
use size::{Size, Base, Style};
let file_size = Size::from_bytes(1_340_249); // same as before
let textual_size = file_size.format()
.with_base(Base::Base10)
.with_style(Style::FullLowercase)
.to_string();
assert_eq!(textual_size, "1.34 megabytes".to_string());It is also possible to create and configure a standalone SizeFormatter that can be reused to
format many sizes in a single, consistent style. This should not be seen as an alternative to
wrapping file sizes in strongly-typed Size structs, which should always be the initial
instinct.
§Mathematical operations
You can perform mathematical operations on Size types and the type safety makes sure that
what you’re doing makes sense:
use size::Size;
let sum = Size::from_mib(2) + Size::from_kib(200);
assert_eq!(sum, Size::from_mb(2.301_952));
let size = Size::from_gb(4.2) / 2;
assert_eq!(size, Size::from_gb(2.1));See the documentation of the ops module for more on this topic.
§Crate features
This crate currently has one feature (std), enabled by default. If compiled with
--no-default-features or used as a dependency with default features disabled, the crate
becomes no_std compatible. When used in no_std mode, the following restrictions and
limitations are observed:
- All formatting/stringification of
Sizetypes is disabled. Sizeno longer implementsstd::fmt::Display(core::fmt::Debugis still implemented).- The intermediate type used for mathematical operations on
Sizetypes is changed fromf64toi64so that no implicit floating-point math is performed. To prevent inadvertent loss of precision, it is forbidden to pass in floating point values to theSizeAPI underno_stdmode.
Re-exports§
pub use crate::fmt::Base;pub use crate::fmt::SizeFormatter;pub use crate::fmt::Style;
Modules§
- A collection of constants for base-2 and base-10 units.
- The
fmtmodule containsSizeFormatterand other types pertaining to formatting a size as human-readable text. - Implementations of basic arithmetic operations on/between
Sizevalues.
Structs§
Sizeis the core type exposed by this crate and allows the developer to express a file size (or the general concept of a “size”) as a strongly-typed, convertible type that can be used for textual formatting (“pretty printing”) and mathematical operations.